﻿using System;
using System.Collections.Generic;
using System.Security.Principal;
using System.IO;
using System.ServiceProcess;
using System.Linq;
using System.Diagnostics;
using System.Management;

namespace TestApp
{
    /// <summary>
    /// Hyper-V Validation Rules based on the hvRemote script by John Howard
    /// http://code.msdn.microsoft.com/HVRemote
    /// http://blogs.technet.com/b/jhoward/archive/2008/11/14/configure-hyper-v-remote-management-in-seconds.aspx
    /// </summary>
    internal class ValidationRule
    {
        #region Instance Members
        public string Name { get; set; }
        public Func<ValidationResult> Check;
        public bool Result { get; set; }
        public string Message { get; set; }

        public ValidationRule(string name)
        {
            Name = name;
        }
        #endregion

        #region Validation Rule Definitions

        public static List<ValidationRule> AllValidationRules;

        static ValidationRule()
        {
            AllValidationRules = new List<ValidationRule>()
            {
                //new ValidationRule("Empty Rule")
                //{
                //    Check = delegate
                //    {
                //        bool result = true;

                //        return new ValidationResult(result)
                //        {
                //            Message = result ?
                //                "Empty Rule"
                //                :
                //                "Empty Rule"
                //        };
                //    }
                //},
                new ValidationRule("Interactive User is an Administrator.")
                {
                    Check = delegate
                    {
                        var windowsIdentity = WindowsIdentity.GetCurrent();
                        bool result = (new WindowsPrincipal(windowsIdentity)).IsInRole(WindowsBuiltInRole.Administrator);

                        return new ValidationResult(result)
                        {
                            Message = result ?
                                string.Format("Interactive user ({1}) is an {0}.", WindowsBuiltInRole.Administrator.ToString(), windowsIdentity.Name)
                                :
                                string.Format("Interactive user ({1}) is not a member of {0}.", WindowsBuiltInRole.Administrator.ToString(), windowsIdentity.Name)
                        };
                    }
                },
                new ValidationRule("UAC: Confirm user is running Elevated.")
                {
                    Check = delegate
                    {
                        bool result = false;

                        result = CommandLineTest("whoami", "/groups", requiredOutputSubstring:"S-1-16-12288");

                        return new ValidationResult(result)
                        {
                            IsFatal = false,
                            Message = result ?
                                "UAC Check Pass: User is running Elevated."
                                :
                                "UAC Check Fail: User is not running Elevated."
                        };
                    }
                },
                new ValidationRule("Hyper-V Service Check: VMMS")
                {
                    Check = delegate
                    {
                        bool result = ServiceController.GetServices().Any<ServiceController>((sc) => sc.ServiceName == "vmms" && sc.Status == ServiceControllerStatus.Running);

                        return new ValidationResult(result)
                        {
                            Message = result ?
                                "Windows Service exists and is in the Running state: Hyper-V Virtual Machine Management"
                                :
                                "Windows Service Not Found or Nor Running: Hyper-V Virtual Machine Management"
                        };
                    }
                },
                new ValidationRule("Hyper-V Service Check: NVSPWMI")
                {
                    Check = delegate
                    {
                        bool result = ServiceController.GetServices().Any<ServiceController>((sc) => sc.ServiceName == "nvspwmi" && sc.Status == ServiceControllerStatus.Running);

                        return new ValidationResult(result)
                        {
                            Message = result ?
                                "Windows Service exists and is in the Running state: Hyper-V Networking Management Service"
                                :
                                "Windows Service Not Found or Nor Running: Hyper-V Networking Management Service"
                        };
                    }
                },
                new ValidationRule("Hyper-V Service Check: VHDSVC")
                {
                    Check = delegate
                    {
                        bool result = ServiceController.GetServices().Any<ServiceController>((sc) => sc.ServiceName == "vhdsvc" && sc.Status == ServiceControllerStatus.Running);

                        return new ValidationResult(result)
                        {
                            Message = result ?
                                "Windows Service exists and is in the Running state: Hyper-V Image Management Service"
                                :
                                "Windows Service Not Found or Nor Running: Hyper-V Image Management Service"
                        };
                    }
                },
                new ValidationRule("System Center Virtual Machine Manager Service Check: VMMAgent")
                {
                    Check = delegate
                    {
                        bool result = ServiceController.GetServices().All<ServiceController>((sc) => sc.ServiceName != "vmmagent");

                        return new ValidationResult(result)
                        {
                            Message = result ?
                                "System Center Virtual Machine Manager Windows Service does not exist."
                                :
                                "System Center Virtual Machine Manager Windows Service was found."
                        };
                    }
                },
                //new ValidationRule("Hyper-V Authorization Store Exists") 
                //{
                //    Check = delegate
                //    {
                //        bool result = File.Exists(HypervAzManStore.DefaultInitialStorePath);

                //        return new ValidationResult(result)
                //        {
                //            Message = result ?
                //                "Hyper-V Authorization Store (InitialStore.xml) exists in default location."
                //                :
                //                "Hyper-V Authorization Store (InitialStore.xml) does not exist in default location."
                //        };
                //    }
                //},
                new ValidationRule("Server is in a Domain.")
                {
                    Check = delegate
                    {
                        try
                        {
                            var dom = System.DirectoryServices.ActiveDirectory.Domain.GetComputerDomain();
                        
                            return new ValidationResult(true)
                            {
                                IsFatal = false,
                                Message = "The current computer is joined to the domain " + dom.Name
                            };
                        }
                        catch (Exception ex)
                        {
                            return new ValidationResult(false)
                            {
                                IsFatal = false,
                                Message = ex.Message
                            };
                        }
                    }
                },
                //new ValidationRule("Interactive User is a Domain Account.")
                //{
                //    Check = delegate
                //    {
                //        try
                //        {
                //            var domUser = System.DirectoryServices.ActiveDirectory.Domain.GetCurrentDomain();

                //            return new ValidationResult(true)
                //            {
                //                Message = "Interactive User Account is in domain " + domUser.Name
                //            };
                //        }
                //        catch (Exception ex)
                //        {
                //            return new ValidationResult(true)
                //            {
                //                Message = ex.Message
                //            };
                //        }
                //    }
                //}
            };
        }
        #endregion

        private static bool CommandLineTest(string cmd, string args, string requiredOutputSubstring)
        {
            using (var procCmd = Process.Start(
                new ProcessStartInfo()
                {
                    FileName = cmd,
                    Arguments = args,
                    CreateNoWindow = true,
                    UseShellExecute = false,
                    RedirectStandardOutput = true
                }))
            {
                procCmd.WaitForExit();
                return procCmd.StandardOutput.ReadToEnd().Contains(requiredOutputSubstring);
            }
        }
    }
}